﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace INSTA.AI97.Samples.Polymorphisme
{
    class Program
    {
        static void Main(string[] args)
        {

            //Test_Poly_Héritage();

            Test_Poly_Interfaces();


        }

        private static void Test_Poly_Interfaces()
        {
            Car a = new Jag();
            Car b = new Clio();
            Car c = new AstonMartin();


            Article x = new Skirt();
            Article y = new Shoes();
            Article z = new TShirt();

            IPriceable[] prices = new IPriceable[6]{ a, b, c, x,y, z};

            // Pour faire imprimer le prix de chacun des
            // éléments du tableau..

            foreach (IPriceable item in prices)
            {
                Console.WriteLine("{0} : Prix {1}",
                                   item.GetType().Name,
                                   item.GetPrice());

                if (item is IPetrolConsumer)
                {
                    Console.WriteLine(" Consomme {0} litres au 100.",
                                      (item as IPetrolConsumer).GetConso());    
                }

                Console.WriteLine();
            }


            object[] prices2 = new object[] 
            { a, b, c, x, y, z, new StringBuilder() };

            foreach (object item in prices2)
            {
                // On vérifie que l'objet en cours dans la boucle
                // peut être casté en IPriceable..
                if (item is IPriceable)
                {
                    // On le caste..
                    IPriceable objetCasté = item as IPriceable;
                    //IPriceable objetCasté = (IPriceable)item;

                    string className = item.GetType().Name;

                    Console.WriteLine("A {0} costs {1} €",
                                      className,
                                      objetCasté.GetPrice()); 

                }
                
            }
        }



        private static void Test_Poly_Héritage()
        {
            //Car poly = new Clio();
            //poly.Accelerate();


            Car x = new AstonMartin();


            // Syntaxe de cast 1 (si le cast échoue génère 
            // une Exception de type InvalidCastException)..
            AstonMartin a = (AstonMartin)x;
            a.Boost();

            // Syntaxe de cast 2, préférable pour les classes..
            AstonMartin b = x as AstonMartin;
            // Si le cast a échoué, on aura une référence nulle
            // dans la variable b.
            if (b != null)
            {
                Console.WriteLine("Cast Réussi");
            }


            // Syntaxe de cast 2 (bis) avec "is" et "as"
            if (x is AstonMartin)
            {
                AstonMartin aston = x as AstonMartin;
                aston.Boost();
            }



            Car[] cars = new Car[2];

            cars[0] = new AstonMartin();
            cars[1] = new Clio();

            foreach (Car element in cars)
            {
                element.Accelerate();

                if (element is AstonMartin)
                {
                    AstonMartin aston = element as AstonMartin;
                    aston.Boost();
                }
            }

            Car j = new Jag();

        }
    }









    abstract class Car :  IPriceable, IPetrolConsumer
    {
        public abstract void Accelerate();

        /// <summary>
        /// Méthode de l'interface <see cref="IPriceable"/>
        /// </summary>
        /// <returns>Le prix.</returns>
        public abstract double GetPrice();

        public abstract double GetConso();
        
    }


    class Jag : Car
    {
        public override void Accelerate()
        {
            Console.WriteLine("Jag.Accelerate() : 65 km/h");
        }
        
        public override double GetPrice()
        {
            return 120000;        
        }

        public override double GetConso()
        {
            return 15;
        }

    }

    class Clio : Car
    {
        public void Reparer()
        {
            Console.WriteLine("Réparation");
        }

        public override void Accelerate()
        {
            Console.WriteLine("Clio.Accelerate() : 10 km/h");            
        }

        public override double GetPrice()
        {
            return 7000;
        }

        public override double GetConso()
        {
            return 3;
        }

    }

    class AstonMartin : Car
    {
        public void Boost()
        {
            Console.WriteLine("Boost");
        }

        public override void Accelerate()
        {
            Console.WriteLine("AstonMartin.Accelerate() : 90 km/h");
        }


        public override double GetPrice()
        {
            return 240000;
        }

        public override double GetConso()
        {
            return 20;
        }
    }


}
